summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Blake Kongslie2022-10-15 14:12:31 -0700
committerJulian Blake Kongslie2022-10-15 14:12:31 -0700
commitecf940e34b42f78f9651a73e8bcd0c6dc3c75cb5 (patch)
tree36a290bf7a6ed585cf040964c8e7481f4df1d631
parentMove shared_bus into arbiter (diff)
downloadbiggolf-ecf940e34b42f78f9651a73e8bcd0c6dc3c75cb5.tar.xz
Depend on external nanosim dependency.
Diffstat (limited to '')
-rw-r--r--.gitmodules3
-rw-r--r--Makefile8
-rw-r--r--infra/arbiter.h55
-rw-r--r--infra/pipetrace.cpp9
-rw-r--r--infra/pipetrace.h37
-rw-r--r--infra/port.h45
-rw-r--r--infra/queue.h29
-rw-r--r--infra/sim.cpp9
-rw-r--r--infra/sim.h38
-rw-r--r--infra/stat.h35
-rw-r--r--memory/dram.h96
-rw-r--r--memory/line.h15
m---------nanosim0
l---------[-rwxr-xr-x]pt105
-rwxr-xr-xtest58
15 files changed, 11 insertions, 531 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..fd231f7
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
1[submodule "nanosim"]
2 path = nanosim
3 url = ../nanosim
diff --git a/Makefile b/Makefile
index 65cc016..5c1228b 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ PALBART := palbart
15 15
16override CXXFLAGS += -std=c++20 16override CXXFLAGS += -std=c++20
17 17
18override COMPILE_FLAGS := -MMD -MP -I. 18override COMPILE_FLAGS := -MMD -MP -I. -Inanosim
19override LINK_FLAGS := 19override LINK_FLAGS :=
20 20
21ifneq "$(strip $(PACKAGES))" "" 21ifneq "$(strip $(PACKAGES))" ""
@@ -33,6 +33,12 @@ clean:
33.SECONDARY: 33.SECONDARY:
34.SUFFIXES: 34.SUFFIXES:
35 35
36nanosim/.present:
37 git submodule update --init --recursive
38 @touch $@
39
40-include nanosim/.present
41
36override SOURCES := $(shell find -\( -name build -prune -\) -o -\( -\( -name \*.bin -o -name \*.cpp -o -name \*.pal -\) -print -\)) 42override SOURCES := $(shell find -\( -name build -prune -\) -o -\( -\( -name \*.bin -o -name \*.cpp -o -name \*.pal -\) -print -\))
37 43
38override OBJECTS := $(addprefix $(BUILD)/, $(addsuffix .o, $(basename $(SOURCES)))) 44override OBJECTS := $(addprefix $(BUILD)/, $(addsuffix .o, $(basename $(SOURCES))))
diff --git a/infra/arbiter.h b/infra/arbiter.h
deleted file mode 100644
index 79a9920..0000000
--- a/infra/arbiter.h
+++ /dev/null
@@ -1,55 +0,0 @@
1#pragma once
2
3#include <array>
4#include <cassert>
5
6#include "infra/sim.h"
7
8namespace infra {
9 template<typename T, unsigned int peers> struct priority_arbiter : public sim {
10 std::array<port<T>, peers> peerp;
11 port<T> *outp = nullptr;
12
13 void clock() {
14 for (unsigned int i = 0; i < peers; ++i) {
15 if (outp->can_write() && peerp[i].can_read())
16 outp->write(peerp[i].read());
17 }
18 }
19 };
20
21 template<typename T, unsigned int peers> struct round_robin_arbiter : public sim {
22 std::array<port<T>, peers> peerp;
23 port<T> *outp = nullptr;
24 unsigned int initial = 0;
25
26 void clock() {
27 bool initially_empty = outp->can_write();
28 for (unsigned int i = initial; i < peers; ++i) {
29 if (outp->can_write() && peerp[i].can_read())
30 outp->write(peerp[i].read());
31 }
32 for (unsigned int i = 0; i < initial; ++i) {
33 if (outp->can_write() && peerp[i].can_read())
34 outp->write(peerp[i].read());
35 }
36 if (initially_empty && !outp->can_write())
37 if (++initial == peers)
38 initial = 0;
39 }
40 };
41
42 template<typename T, unsigned int peers> struct shared_bus : public sim {
43 std::array<port<T>, peers> peerp;
44 port<T> *outp = nullptr;
45
46 void clock() {
47 for (unsigned int i = 0; i < peers; ++i) {
48 if (peerp[i].can_read()) {
49 assert(outp->can_write());
50 outp->write(peerp[i].read());
51 }
52 }
53 }
54 };
55}
diff --git a/infra/pipetrace.cpp b/infra/pipetrace.cpp
deleted file mode 100644
index e6642ef..0000000
--- a/infra/pipetrace.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
1#include <cstdint>
2#include <ostream>
3
4#include "infra/pipetrace.h"
5
6namespace infra {
7 std::ostream *pt::ptfile = nullptr;
8 std::uint64_t pt::next_record = 0;
9}
diff --git a/infra/pipetrace.h b/infra/pipetrace.h
deleted file mode 100644
index 656b9b9..0000000
--- a/infra/pipetrace.h
+++ /dev/null
@@ -1,37 +0,0 @@
1#pragma once
2
3#include <cstdint>
4#include <fmt/format.h>
5#include <ostream>
6#include <string>
7
8namespace infra {
9 struct transaction {
10 std::uint64_t record = ~(std::uint64_t)0;
11 };
12
13 struct pt {
14 static std::ostream *ptfile;
15
16 static std::uint64_t next_record;
17
18 static transaction toplevel() {
19 transaction t;
20 t.record = next_record++;
21 return t;
22 }
23
24 static transaction child(const transaction &p) {
25 transaction t;
26 t.record = next_record++;
27 if (ptfile)
28 *ptfile << fmt::format("{} parent {}\n", t.record, p.record);
29 return t;
30 }
31
32 static void event(const transaction &t, const char *event, std::uint64_t time, const std::string &data) {
33 if (ptfile)
34 *ptfile << fmt::format("@{} {} {} {}\n", time, t.record, event, data);
35 }
36 };
37}
diff --git a/infra/port.h b/infra/port.h
deleted file mode 100644
index 06a3aa5..0000000
--- a/infra/port.h
+++ /dev/null
@@ -1,45 +0,0 @@
1#pragma once
2
3#include <cassert>
4#include <optional>
5#include <utility>
6
7#include "infra/sim.h"
8
9namespace infra {
10 template<typename T> struct port : public sim {
11 std::optional<T> consumer_side;
12 std::optional<T> producer_side;
13
14 bool can_read() { return consumer_side.has_value(); }
15 bool can_write() { return !producer_side.has_value(); }
16
17 T read() {
18 assert(can_read());
19 auto x = std::move(*consumer_side);
20 consumer_side.reset();
21 return x;
22 }
23
24 const T & peek() {
25 assert(can_read());
26 return *consumer_side;
27 }
28
29 void discard() {
30 consumer_side.reset();
31 }
32
33 void write(T &&x) {
34 assert(can_write());
35 producer_side = std::move(x);
36 }
37
38 void unclock() {
39 if (!consumer_side && producer_side) {
40 consumer_side = std::move(*producer_side);
41 producer_side.reset();
42 }
43 }
44 };
45}
diff --git a/infra/queue.h b/infra/queue.h
deleted file mode 100644
index 1e490bc..0000000
--- a/infra/queue.h
+++ /dev/null
@@ -1,29 +0,0 @@
1#pragma once
2
3#include <cassert>
4#include <deque>
5#include <optional>
6#include <utility>
7
8#include "infra/port.h"
9#include "infra/sim.h"
10
11namespace infra {
12 template<typename T, unsigned int size> struct queue : public sim {
13 port<T> input;
14 port<T> *output = nullptr;
15 std::deque<T> elements;
16
17 void clock() {
18 if (input.can_read() && elements.size() < size) {
19 auto x = input.read();
20 elements.emplace_back(std::move(x));
21 }
22 if (output->can_write() && !elements.empty()) {
23 auto &x = elements.front();
24 output->write(std::move(x));
25 elements.pop_front();
26 }
27 }
28 };
29}
diff --git a/infra/sim.cpp b/infra/sim.cpp
deleted file mode 100644
index 21acc8c..0000000
--- a/infra/sim.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
1#include <cstdint>
2#include <vector>
3
4#include "infra/sim.h"
5
6namespace infra {
7 std::vector<sim *> sim::sims;
8 std::uint64_t sim::now = 0;
9}
diff --git a/infra/sim.h b/infra/sim.h
deleted file mode 100644
index 185916a..0000000
--- a/infra/sim.h
+++ /dev/null
@@ -1,38 +0,0 @@
1#pragma once
2
3#include <cstdint>
4#include <string>
5#include <vector>
6
7#include "infra/pipetrace.h"
8
9namespace infra {
10 struct sim {
11 virtual void clock() {}
12 virtual void unclock() {}
13
14 static std::vector<sim *> sims;
15
16 static std::uint64_t now;
17
18 sim() {
19 sims.emplace_back(this);
20 }
21
22 virtual ~sim() {
23 std::erase(sims, this);
24 }
25
26 static void advance() {
27 for (auto &s : sims)
28 s->clock();
29 for (auto &s : sims)
30 s->unclock();
31 ++now;
32 }
33
34 void pte(const transaction &t, const char *event, const std::string &data) {
35 pt::event(t, event, now, data);
36 }
37 };
38}
diff --git a/infra/stat.h b/infra/stat.h
deleted file mode 100644
index f1ca75a..0000000
--- a/infra/stat.h
+++ /dev/null
@@ -1,35 +0,0 @@
1#pragma once
2
3#include <fmt/format.h>
4#include <utility>
5
6#include "infra/sim.h"
7
8namespace infra {
9 struct stat : public sim {
10 std::string name;
11 std::uint64_t numerator = 0;
12 std::uint64_t denominator = 0;
13
14 stat(std::string name)
15 : name(std::move(name))
16 { }
17
18 ~stat() {
19 fmt::print("# {} {}\n", name, (double)numerator/(double)denominator);
20 }
21
22 void unclock() {
23 ++denominator;
24 }
25
26 stat & operator++() {
27 ++numerator;
28 return *this;
29 }
30
31 stat & operator++(int) {
32 return operator++();
33 }
34 };
35}
diff --git a/memory/dram.h b/memory/dram.h
deleted file mode 100644
index f59c7a6..0000000
--- a/memory/dram.h
+++ /dev/null
@@ -1,96 +0,0 @@
1#pragma once
2
3#include <array>
4#include <cstdint>
5#include <cstring>
6#include <istream>
7#include <map>
8#include <string>
9#include <utility>
10
11#include "memory/line.h"
12
13namespace memory {
14 struct dram : public infra::sim {
15 static constexpr std::uint64_t PAGE_LINES_LOG2 = 20 - LINE_BYTES_LOG2;
16 static constexpr std::uint64_t PAGE_LINES = 1 << PAGE_LINES_LOG2;
17 static constexpr std::uint64_t PAGE_LINE_OFFSET_MASK = PAGE_LINES - 1;
18 static constexpr std::uint64_t PAGE_BYTES_LOG2 = PAGE_LINES_LOG2 + LINE_BYTES_LOG2;
19 static constexpr std::uint64_t PAGE_BYTES = 1 << PAGE_BYTES_LOG2;
20 static constexpr std::uint64_t PAGE_BYTE_OFFSET_MASK = PAGE_BYTES - 1;
21
22 typedef std::array<line, PAGE_LINES> page;
23
24 std::map<std::uint64_t, page> image;
25
26 struct response {
27 infra::transaction transaction;
28 std::uint64_t line_address;
29 line data;
30 };
31
32 struct command {
33 infra::transaction transaction;
34 std::uint64_t line_address;
35 line data;
36 std::array<bool, LINE_BYTES> mask;
37 bool write = false;
38 infra::port<response> *responsep = nullptr;
39 };
40
41 infra::port<command> commandp;
42
43 void clock() {
44 if (commandp.can_read()) {
45 const auto &c = commandp.peek();
46 if (!c.responsep || c.responsep->can_write()) {
47 auto page_address = c.line_address >> PAGE_LINES_LOG2;
48 auto page_line = c.line_address & PAGE_LINE_OFFSET_MASK;
49 if (c.write) {
50 pte(c.transaction, "s", fmt::format("store {:x}-{:x}", page_address, page_line));
51 if (c.responsep) {
52 response r;
53 r.transaction = c.transaction;
54 r.line_address = c.line_address;
55 r.data = c.data;
56 c.responsep->write(std::move(r));
57 }
58 auto [p, emplaced] = image.try_emplace(page_address);
59 if (emplaced)
60 for (unsigned int i = 0; i < PAGE_LINES; ++i)
61 p->second[i].fill(0);
62 auto &l = p->second[page_line];
63 for (unsigned int i = 0; i < LINE_BYTES; ++i)
64 if (c.mask[i])
65 l[i] = c.data[i];
66 } else {
67 pte(c.transaction, "f", fmt::format("fill {:x}-{:x}", page_address, page_line));
68 if (c.responsep) {
69 response r;
70 r.transaction = c.transaction;
71 r.line_address = c.line_address;
72 if (auto p = image.find(page_address); p != image.end())
73 r.data = p->second[page_line];
74 else
75 r.data.fill(0);
76 c.responsep->write(std::move(r));
77 }
78 }
79 commandp.discard();
80 }
81 }
82 }
83
84 void load(std::istream &fh) {
85 for (unsigned int page = 0; ; ++page) {
86 auto [p, emplaced] = image.try_emplace(page);
87 if (emplaced)
88 for (unsigned int i = 0; i < PAGE_LINES; ++i)
89 p->second[i].fill(0);
90 for (unsigned int line = 0; line < PAGE_LINES; ++line)
91 if (!fh.read(reinterpret_cast<char *>(p->second[line].data()), LINE_BYTES))
92 return;
93 }
94 }
95 };
96}
diff --git a/memory/line.h b/memory/line.h
deleted file mode 100644
index 3377ec8..0000000
--- a/memory/line.h
+++ /dev/null
@@ -1,15 +0,0 @@
1#pragma once
2
3#include <array>
4#include <cstdint>
5
6#include "infra/port.h"
7#include "infra/sim.h"
8
9namespace memory {
10 constexpr std::uint64_t LINE_BYTES_LOG2 = 4;
11 constexpr std::uint64_t LINE_BYTES = 1 << LINE_BYTES_LOG2;
12 constexpr std::uint64_t LINE_BYTE_OFFSET_MASK = LINE_BYTES - 1;
13
14 typedef std::array<std::uint8_t, LINE_BYTES> line;
15}
diff --git a/nanosim b/nanosim
new file mode 160000
Subproject fb6c230eb8139006c954e8906690009c4f040c4
diff --git a/pt b/pt
index 206795f..d6f3bd4 100755..120000
--- a/pt
+++ b/pt
@@ -1,104 +1 @@
1#!/usr/bin/ruby nanosim/pt \ No newline at end of file
2
3$filter = ARGV
4
5$parents = {}
6$events = {}
7$has = {}
8$data = {}
9$horiz = {}
10$maxtime = -1
11
12$stats = false
13
14$stdin.each_line do | line |
15 case line
16
17 when /^(\d+) parent (\d+)$/
18 child = $1.to_i
19 parent = $2.to_i
20 $parents[child] = parent
21
22 when /^@(\d+) (\d+) (\S*) (.*)$/
23 time = $1.to_i
24 rec = $2.to_i
25 event = $3
26 data = $4
27 if event.size > 0
28 $events[rec] ||= {}
29 $events[rec][time] = event
30 $has[rec] ||= {}
31 $has[rec][event] = true
32 $horiz[event] ||= ""
33 $horiz[event] = $horiz[event].ljust(time)
34 $horiz[event][time] = event
35 end
36 if data.size > 0
37 $data[rec] ||= ""
38 $data[rec] += " #{event}@#{time}:" if event.size > 0
39 $data[rec] += " #{data}"
40 end
41 $maxtime = [$maxtime, time+1].max
42
43 when /^#\s*(.*)$/
44 $stats = true
45 $stdout.write("#{$1}\n")
46
47 else
48 raise "Unexpected line: #{line}"
49 end
50end
51
52$stdout.write("\n") if $stats
53
54$hier = {}
55$hier_direct = {}
56
57$events.each_key do | rec |
58 subhier = {}
59 $hier_direct[rec] = subhier
60 if $parents.key?(rec)
61 $hier_direct[$parents[rec]][rec] = subhier
62 else
63 $hier[rec] = subhier
64 end
65end
66
67$order = []
68
69def flatten(hier)
70 hier.each do | rec, subhier |
71 $order << rec
72 flatten(subhier)
73 end
74end
75flatten($hier)
76
77rwidth = $order.map { | x | x.to_s.size }.max
78
79$horiz.keys.sort.each do | occ |
80 $stdout.write(" " * rwidth + " #{$horiz[occ].ljust($maxtime)}")
81 count = $horiz[occ].delete(" ").size
82 $stdout.write(" #{($maxtime.to_f / count.to_f).round(2).to_s.rjust(5)} cyc/evt\n")
83end
84$stdout.write("\n")
85
86mwidth = 0
87
88$order.each do | rec |
89 estr = ""
90 filter_match = $filter.empty?
91 $has[rec].each_key do | event |
92 filter_match ||= $filter.include?(event)
93 end
94 next unless filter_match
95 $events[rec].keys.sort.each do | time |
96 estr = estr.ljust(time + 1, estr.size == 0 ? " " : "-")
97 estr[time] = $events[rec][time] if $events[rec][time].size > 0
98 end
99 estr += " " * 5
100 estr = estr.ljust(mwidth - 1)
101 estr = estr.ljust(estr.size + 20 - estr.size % 20)
102 mwidth = [mwidth, estr.size].max
103 $stdout.write(rec.to_s.rjust(rwidth) + ": #{estr}#{$data[rec]}\n")
104end
diff --git a/test b/test
deleted file mode 100755
index d70c720..0000000
--- a/test
+++ /dev/null
@@ -1,58 +0,0 @@
1#!/bin/bash
2
3set -eu
4
5FILTER=()
6
7while [[ $# != 0 ]]; do
8 if [[ $1 == "-h" ]]; then
9 cat <<END
10Usage: ./test [options ...] [tests ...]
11
12Options:
13 -h This help message
14 -e Show emit rows
15 -f Show fetch rows
16 -i Show instruction rows
17 -m Show rows with memory traffic
18 -r Show rows with writeback (retire)
19
20For the filtering options: if one or more filters are set, then rows which
21match any filter are shown. If no filter is set, then all rows are shown.
22END
23 exit
24 elif [[ $1 == "-e" ]]; then
25 shift
26 FILTER+=("*")
27 elif [[ $1 == "-f" ]]; then
28 shift
29 FILTER+=("F")
30 elif [[ $1 == "-i" ]]; then
31 shift
32 FILTER+=("D")
33 elif [[ $1 == "-m" ]]; then
34 shift
35 FILTER+=("f" "s")
36 elif [[ $1 == "-r" ]]; then
37 shift
38 FILTER+=("W")
39 else
40 break
41 fi
42done
43
44if [[ $# == 0 ]]; then
45 for TEST in $(ls -1 tests); do
46 set -- "$@" "${TEST%.hex}"
47 done
48fi
49
50make
51
52for TEST in "$@"; do
53 make "build/tests/$TEST.bin"
54 (
55 echo "$TEST"
56 ./procmodel "build/tests/$TEST.bin" | ./pt "${FILTER[@]}"
57 ) | less -S
58done