summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Blake Kongslie2021-07-06 09:44:36 -0700
committerJulian Blake Kongslie2021-07-06 09:44:36 -0700
commit60e1775b874015a3451e4bde10a8eb30701b1165 (patch)
tree477a2835c0f7e616bdeeabe6aee85f8af8b79650
downloadbreadboarding-60e1775b874015a3451e4bde10a8eb30701b1165.tar.xz
Initial commit.
-rw-r--r--.gitignore1
-rw-r--r--Makefile7
-rwxr-xr-xasm.rb196
-rw-r--r--boards/decode/decode.kicad_pcb1
-rw-r--r--boards/decode/decode.pro33
-rw-r--r--boards/decode/decode.sch4
-rw-r--r--fib.s21
-rw-r--r--insts.rb228
-rw-r--r--modules.rb32
-rw-r--r--sim/.gitignore2
-rw-r--r--sim/Makefile12
-rw-r--r--sim/alu.sv76
-rw-r--r--sim/control.sv54
-rw-r--r--sim/decode.sv82
-rw-r--r--sim/main.cpp61
-rw-r--r--sim/memory.sv35
-rw-r--r--sim/pc.sv36
-rw-r--r--sim/rf.sv39
-rw-r--r--sim/tmp.sv41
-rw-r--r--sim/top.sv27
-rw-r--r--sim/uart.sv47
-rw-r--r--sim/urom.sv19
-rwxr-xr-xuasm.rb174
-rw-r--r--vectors.rb7
24 files changed, 1235 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e2e7327
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
/out
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..31000b8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
1run: out/image.hex
2 $(MAKE) -C sim
3.PHONY: run
4
5out/image.hex: fib.s $(wildcard *.rb)
6 ./uasm.rb
7 ./asm.rb $< | expand -t 24 > $@
diff --git a/asm.rb b/asm.rb
new file mode 100755
index 0000000..2ca9155
--- /dev/null
+++ b/asm.rb
@@ -0,0 +1,196 @@
1#!/usr/bin/ruby -w
2
3$insts = {}
4
5$next_opcode = 0
6
7def inst(pattern, vector=false, &code)
8 return if vector
9 throw "instruction with this pattern already defined" if $insts.member?(pattern)
10 $insts[pattern] = $next_opcode
11 $next_opcode += 1
12end
13
14load "insts.rb"
15
16$labels = {}
17$pc = 0
18
19ARGF.each_line do | line |
20 line.chomp!
21 line.gsub!(/^\s+/, "")
22 line.gsub!(/#.*/, "")
23 line.gsub!(/\s+$/, "")
24
25 next if line == ""
26
27 if line =~ /^([a-zA-Z_][a-zA-Z0-9_]*):$/
28 $labels[$1] = $pc
29 $stdout.write("\t// #{line}\n")
30 next
31 elsif line =~ /^\.origin\s+((?:0x[0-9a-fA-F]+)?(?:\d+))$/
32 $pc = $1.to_i(0)
33 $stdout.write("@#{$pc.to_s(16)}\t// #{line}\n")
34 next
35 elsif line =~ /^\.bytes?\s+(.*)$/
36 data = $1.split(/\s+/)
37 data.map { | x | throw "invalid byte #{x}" unless x =~ /^-?(?:(?:0x[0-9a-fA-F]+)|(?:\d+))$/ }
38 data = data.map { | x | x.to_i(0) }
39 data = data.map { | x | x < 0 ? x + 0x100 : x }
40 data.map { | x | throw "invalid byte 0x#{x.to_s(16)}" unless x >= 0 && x <= 0xff }
41 data = data.map { | x | x.to_s(16).rjust(2, "0") }
42 $pc += data.size
43 $stdout.write("#{data.join(" ")}\t// #{line}\n")
44 next
45 elsif line =~ /^\.shorts?\s+(.*)$/
46 data = $1.split(/\s+/)
47 data.map { | x | throw "invalid short #{x}" unless x =~ /^-?(?:(?:0x[0-9a-fA-F]+)|(?:\d+))$/ }
48 data = data.map { | x | x.to_i(0) }
49 data = data.map { | x | x < 0 ? x + 0x10000 : x }
50 data.map { | x | throw "invalid short 0x#{x.to_s(16)}" unless x >= 0 && x <= 0xffff }
51 data = data.flat_map { | x | [x & 0xff, x >> 8] }
52 data = data.map { | x | x.to_s(16).rjust(2, "0") }
53 $pc += data.size
54 $stdout.write("#{data.join(" ")}\t// #{line}\n")
55 next
56 elsif line =~ /^\.longs?\s+(.*)$/
57 data = $1.split(/\s+/)
58 data.map { | x | throw "invalid long #{x}" unless x =~ /^-?(?:(?:0x[0-9a-fA-F]+)|(?:\d+))$/ }
59 data = data.map { | x | x.to_i(0) }
60 data = data.map { | x | x < 0 ? x + 0x100000000 : x }
61 data.map { | x | throw "invalid long 0x#{x.to_s(16)}" unless x >= 0 && x <= 0xffffffff }
62 data = data.flat_map { | x | [x & 0xff, (x >> 8) & 0xff, (x >> 16) & 0xff, x >> 24] }
63 data = data.map { | x | x.to_s(16).rjust(2, "0") }
64 $pc += data.size
65 $stdout.write("#{data.join(" ")}\t// #{line}\n")
66 next
67 elsif line =~ /^\.quads?\s+(.*)$/
68 data = $1.split(/\s+/)
69 data.map { | x | throw "invalid quad #{x}" unless x =~ /^-?(?:(?:0x[0-9a-fA-F]+)|(?:\d+))$/ }
70 data = data.map { | x | x.to_i(0) }
71 data = data.map { | x | x < 0 ? x + 0x10000000000000000 : x }
72 data.map { | x | throw "invalid quad 0x#{x.to_s(16)}" unless x >= 0 && x <= 0xffffffffffffffff }
73 data = data.flat_map { | x | [x & 0xff, (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff, (x >> 32) & 0xff, (x >> 40) & 0xff, (x >> 48) & 0xff, x >> 56] }
74 data = data.map { | x | x.to_s(16).rjust(2, "0") }
75 $pc += data.size
76 $stdout.write("#{data.join(" ")}\t// #{line}\n")
77 next
78 end
79
80 parts = line.split(/\s+/)
81
82 patterns = [parts.shift]
83 values = []
84 parts.each do | part |
85 case part
86 when /^(-?(?:(?:0x[0-9a-fA-F]+)|(?:\d+)))$/
87 patterns << "#"
88 values << $1.to_i(0)
89 when /^([a-zA-Z_][a-zA-Z0-9_]+)$/
90 throw "unknown label #{$1}" unless $labels.member?($1)
91 patterns << "#"
92 values << $labels[$1]
93 when /^\$(-?(?:(?:0x[0-9a-fA-F]+)|(?:\d+)))$/
94 patterns << "$"
95 values << $1.to_i(0)
96 when /^\[(-?(?:(?:0x[0-9a-fA-F]+)|(?:\d+)))\]$/
97 patterns << "[#]"
98 values << $1.to_i(0)
99 when /^\[([a-zA-Z_][a-zA-Z0-9_]+)\]$/
100 throw "unknown label #{$1}" unless $labels.member?($1)
101 patterns << "[#]"
102 values << $labels[$1]
103 when /^\[\$(-?(?:(?:0x[0-9a-fA-F]+)|(?:\d+)))\]$/
104 patterns << "[$]"
105 values << $1.to_i(0)
106 else
107 throw "invalid part #{part}"
108 end
109 end
110
111 pattern = patterns.join(" ")
112 throw "unknown instruction pattern #{pattern}" unless $insts.member?(pattern)
113 opcode = $insts[pattern]
114
115 # Encoding format:
116 # +-+-+-+-+-+-+-+-+
117 # |M|I|SEL| SHIFT |
118 # +-+-+-+-+-+-+-+-+
119 # M = More data after this
120 # I = Invert this field before shifting
121 # SEL = Field selector (0=opcode, 2=A, 3=B)
122 # SHIFT = Data to shift in
123
124 # This gives us these common first nibbles:
125 # 0 last opcode byte
126 # 8 extended opcode byte
127 # A operand A byte
128 # B operand B byte
129 # E operand A byte (with inversion)
130 # F operand B byte (with inversion)
131
132 space = false
133 values.each_with_index do | value, idx |
134 inverted = value < 0
135 if inverted
136 value *= -1
137 value -= 1
138 end
139 nibbles = []
140 while value != 0
141 nibbles << (value & 0xf).to_s(16)
142 value = value >> 4
143 end
144 if inverted and nibbles.empty?
145 nibbles << "f"
146 end
147 nibbles.reverse!
148 if idx == 0
149 if inverted
150 $stdout.write(" ") if space
151 $stdout.write("e#{nibbles.shift}")
152 $pc += 1
153 space = true
154 end
155 nibbles.each do | nibble |
156 $stdout.write(" ") if space
157 $stdout.write("a#{nibble}")
158 $pc += 1
159 space = true
160 end
161 elsif idx == 1
162 if inverted
163 $stdout.write(" ") if space
164 $stdout.write("f#{nibbles.shift}")
165 $pc += 1
166 space = true
167 end
168 nibbles.each do | nibble |
169 $stdout.write(" ") if space
170 $stdout.write("b#{nibble}")
171 $pc += 1
172 space = true
173 end
174 else
175 throw "don't know how to encode this many fields"
176 end
177 end
178
179 nibbles = []
180 while opcode != 0
181 nibbles << (opcode & 0xf).to_s(16)
182 opcode = opcode >> 4
183 end
184 nibbles << "0" if nibbles.empty?
185 last = nibbles.shift
186 nibbles.reverse!
187 nibbles.each do | nibble |
188 $stdout.write(" ") if space
189 $stdout.write("8#{nibble}")
190 $pc += 1
191 space = true
192 end
193 $stdout.write(" ") if space
194 $stdout.write("0#{last}\t// #{line}\n")
195 $pc += 1
196end
diff --git a/boards/decode/decode.kicad_pcb b/boards/decode/decode.kicad_pcb
new file mode 100644
index 0000000..02c8ecb
--- /dev/null
+++ b/boards/decode/decode.kicad_pcb
@@ -0,0 +1 @@
(kicad_pcb (version 4) (host kicad "dummy file") )
diff --git a/boards/decode/decode.pro b/boards/decode/decode.pro
new file mode 100644
index 0000000..152769c
--- /dev/null
+++ b/boards/decode/decode.pro
@@ -0,0 +1,33 @@
1update=22/05/2015 07:44:53
2version=1
3last_client=kicad
4[general]
5version=1
6RootSch=
7BoardNm=
8[pcbnew]
9version=1
10LastNetListRead=
11UseCmpFile=1
12PadDrill=0.600000000000
13PadDrillOvalY=0.600000000000
14PadSizeH=1.500000000000
15PadSizeV=1.500000000000
16PcbTextSizeV=1.500000000000
17PcbTextSizeH=1.500000000000
18PcbTextThickness=0.300000000000
19ModuleTextSizeV=1.000000000000
20ModuleTextSizeH=1.000000000000
21ModuleTextSizeThickness=0.150000000000
22SolderMaskClearance=0.000000000000
23SolderMaskMinWidth=0.000000000000
24DrawSegmentWidth=0.200000000000
25BoardOutlineThickness=0.100000000000
26ModuleOutlineThickness=0.150000000000
27[cvpcb]
28version=1
29NetIExt=net
30[eeschema]
31version=1
32LibDir=
33[eeschema/libraries]
diff --git a/boards/decode/decode.sch b/boards/decode/decode.sch
new file mode 100644
index 0000000..fff8c68
--- /dev/null
+++ b/boards/decode/decode.sch
@@ -0,0 +1,4 @@
1EESchema Schematic File Version 2
2EELAYER 25 0
3EELAYER END
4$EndSCHEMATC
diff --git a/fib.s b/fib.s
new file mode 100644
index 0000000..c2e70bf
--- /dev/null
+++ b/fib.s
@@ -0,0 +1,21 @@
1mov $0 0
2mov $1 1
3mov $2 0x8000
4
5loop:
6
7mov [$2] $0
8add $2 1
9
10tx $0
11
12mov $-1 $0
13add $-1 $1
14mov $0 $1
15mov $1 $-1
16
17mov $-1 $2
18eq $-1 0x800a
19jz $-1 loop
20
21hlt
diff --git a/insts.rb b/insts.rb
new file mode 100644
index 0000000..bc9c156
--- /dev/null
+++ b/insts.rb
@@ -0,0 +1,228 @@
1inst "hlt" do
2 @control.halt
3end
4
5inst "mov $ #" do
6 uop { @decode.outaddr_a; @decode.outdata_b; @rf.store }
7end
8
9inst "mov $ $" do
10 uop { @decode.outaddr_b; @rf.outdata; @tmp0.loaddata }
11 uop { @decode.outaddr_a; @tmp0.outdata; @rf.store }
12end
13
14inst "mov [#] #" do
15 uop { @decode.outaddr_a; @decode.outdata_b; @memory.store }
16end
17
18inst "mov [#] $" do
19 uop { @decode.outaddr_b; @rf.outdata; @tmp0.loaddata }
20 uop { @decode.outaddr_a; @tmp0.outdata; @memory.store }
21end
22
23inst "mov [$] #" do
24 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
25 uop { @decode.outdata_b; @tmp0.outaddr; @memory.store }
26end
27
28inst "mov [$] $" do
29 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
30 uop { @decode.outaddr_b; @rf.outdata; @tmp1.loaddata }
31 uop { @tmp0.outaddr; @tmp1.outdata; @memory.store }
32end
33
34inst "mov $ [#]" do
35 uop { @decode.outaddr_b; @memory.outdata; @tmp0.loaddata }
36 uop { @decode.outaddr_a; @tmp0.outdata; @rf.store }
37end
38
39inst "mov $ [$]" do
40 uop { @decode.outaddr_b; @rf.outdata; @tmp0.loaddata }
41 uop { @tmp0.outaddr; @memory.outdata; @tmp1.loaddata }
42 uop { @decode.outaddr_a; @tmp1.outdata; @rf.store }
43end
44
45inst "skipz $" do
46 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
47 uop { @tmp0.outdata; @control.set_uip_if_nonzero; constaddr($eom) }
48 uop { @decode.clear }
49 decode_loop = uip()
50 uop { @pc.increment; @pc.outaddr; @memory.outdata; @decode.decode }
51 uop { @decode.outdata_needmore; @control.set_uip_if_nonzero; constaddr(decode_loop) }
52end
53
54inst "skipnz $" do
55 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
56 uop { @tmp0.outdata; @control.set_uip_if_nonzero; constaddr(uip()+2) }
57 uop { @control.set_uip; constaddr($eom) }
58 uop { @decode.clear }
59 decode_loop = uip()
60 uop { @pc.increment; @pc.outaddr; @memory.outdata; @decode.decode }
61 uop { @decode.outdata_needmore; @control.set_uip_if_nonzero; constaddr(decode_loop) }
62end
63
64inst "push $ #" do
65 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
66 uop { @tmp0.outaddr; @alu.sub; constdata(1) }
67 uop { @decode.outaddr_a; @alu.outdata; @rf.store }
68 uop { @decode.outdata_b; @alu.outaddr; @memory.store }
69end
70
71inst "push $ $" do
72 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
73 uop { @tmp0.outaddr; @alu.sub; constdata(1) }
74 uop { @decode.outaddr_a; @alu.outdata; @rf.store }
75 uop { @decode.outaddr_b; @rf.outdata; @tmp1.loaddata }
76 uop { @tmp1.outdata; @alu.outaddr; @memory.store }
77end
78
79inst "pop $ $" do
80 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
81 uop { @tmp0.outaddr; @alu.add; constdata(1) }
82 uop { @decode.outaddr_a; @alu.outdata; @rf.store }
83 uop { @alu.outaddr; @memory.outdata; @tmp0.loaddata }
84 uop { @decode.outaddr_b; @tmp0.outdata; @rf.store }
85end
86
87def alu(op)
88 inst "#{op} $ #" do
89 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
90 uop { @decode.outdata_b; @tmp0.outaddr; @alu.send(op) }
91 uop { @decode.outaddr_a; @alu.outdata; @rf.store }
92 end
93
94 inst "#{op} $ $" do
95 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
96 uop { @decode.outaddr_b; @rf.outdata; @tmp1.loaddata }
97 uop { @tmp0.outaddr; @tmp1.outdata; @alu.send(op) }
98 uop { @decode.outaddr_a; @alu.outdata; @rf.store }
99 end
100end
101
102alu :and
103alu :or
104alu :xor
105alu :add
106alu :sub
107alu :cmp
108alu :lshift
109alu :rshift
110
111def cmpbit(name, bit)
112 inst "#{name} $ #" do
113 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
114 uop { @decode.outdata_b; @tmp0.outaddr; @alu.cmp }
115 uop { @alu.outdata; @alu.and; constaddr(1<<bit) }
116 uop { @decode.outaddr_a; @alu.outdata; @rf.store }
117 end
118
119 inst "#{name} $ $" do
120 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
121 uop { @decode.outaddr_b; @rf.outdata; @tmp1.loaddata }
122 uop { @tmp0.outaddr; @tmp1.outdata; @alu.cmp }
123 uop { @alu.outdata; @alu.and; constaddr(1<<bit) }
124 uop { @decode.outaddr_a; @alu.outdata; @rf.store }
125 end
126end
127
128cmpbit :lt, 0
129cmpbit :eq, 1
130cmpbit :gt, 2
131cmpbit :lxor, 3
132cmpbit :lor, 4
133cmpbit :land, 5
134
135inst "jmp #" do
136 uop { @decode.outaddr_a; @pc.load }
137end
138
139inst "jmp $" do
140 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
141 uop { @tmp0.outaddr; @pc.load }
142end
143
144inst "jz $ #" do
145 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
146 uop { @tmp0.outdata; @control.set_uip_if_nonzero; constaddr($eom) }
147 uop { @decode.outaddr_b; @pc.load }
148end
149
150inst "jz $ $" do
151 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
152 uop { @tmp0.outdata; @control.set_uip_if_nonzero; constaddr($eom) }
153 uop { @decode.outaddr_b; @rf.outdata; @tmp0.loaddata }
154 uop { @tmp0.outaddr; @pc.load }
155end
156
157inst "jnz $ #" do
158 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
159 uop { @tmp0.outdata; @control.set_uip_if_nonzero; constaddr(uip()+2) }
160 uop { @control.set_uip; constaddr($eom) }
161 uop { @decode.outaddr_b; @pc.load }
162end
163
164inst "jnz $ $" do
165 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
166 uop { @tmp0.outdata; @control.set_uip_if_nonzero; constaddr(uip()+2) }
167 uop { @control.set_uip; constaddr($eom) }
168 uop { @decode.outaddr_b; @rf.outdata; @tmp0.loaddata }
169 uop { @tmp0.outaddr; @pc.load }
170end
171
172inst "rjmp #" do
173 uop { @decode.outdata_a; @pc.outaddr; @alu.add }
174 uop { @alu.outaddr; @pc.load }
175end
176
177inst "rjmp $" do
178 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
179 uop { @tmp0.outdata; @pc.outaddr; @alu.add }
180 uop { @alu.outaddr; @pc.load }
181end
182
183inst "rjz $ #" do
184 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
185 uop { @tmp0.outdata; @control.set_uip_if_nonzero; constaddr($eom) }
186 uop { @decode.outdata_b; @pc.outaddr; @alu.add }
187 uop { @alu.outaddr; @pc.load }
188end
189
190inst "rjz $ $" do
191 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
192 uop { @tmp0.outdata; @control.set_uip_if_nonzero; constaddr($eom) }
193 uop { @decode.outaddr_b; @rf.outdata; @tmp0.loaddata }
194 uop { @tmp0.outdata; @pc.outaddr; @alu.add }
195 uop { @alu.outaddr; @pc.load }
196end
197
198inst "rjnz $ #" do
199 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
200 uop { @tmp0.outdata; @control.set_uip_if_nonzero; constaddr(uip()+2) }
201 uop { @control.set_uip; constaddr($eom) }
202 uop { @decode.outdata_b; @pc.outaddr; @alu.add }
203 uop { @alu.outaddr; @pc.load }
204end
205
206inst "rjnz $ $" do
207 uop { @decode.outaddr_a; @rf.outdata; @tmp0.loaddata }
208 uop { @tmp0.outdata; @control.set_uip_if_nonzero; constaddr(uip()+2) }
209 uop { @control.set_uip; constaddr($eom) }
210 uop { @decode.outaddr_b; @rf.outdata; @tmp0.loaddata }
211 uop { @tmp0.outdata; @pc.outaddr; @alu.add }
212 uop { @alu.outaddr; @pc.load }
213end
214
215inst "rx $" do
216 uop { @uart.outdata_rxempty; @control.set_uip_if_nonzero; constaddr(uip()) }
217 uop { @decode.outaddr_a; @uart.rx; @rf.store }
218end
219
220inst "tx $" do
221 uop { @uart.outdata_txfull; @control.set_uip_if_nonzero; constaddr(uip()) }
222 uop { @decode.outaddr_a; @rf.outdata; @uart.tx }
223end
224
225inst "tx #" do
226 uop { @uart.outdata_txfull; @control.set_uip_if_nonzero; constaddr(uip()) }
227 uop { @decode.outdata_a; @uart.tx }
228end
diff --git a/modules.rb b/modules.rb
new file mode 100644
index 0000000..36d3b83
--- /dev/null
+++ b/modules.rb
@@ -0,0 +1,32 @@
1urom :alu, :op, :op_sel0, :op_sel1, :op_sel2, :outaddr, :outdata
2urom :control, :halt, :set_uip_cond, :nocond, :outaddr, :outdata
3urom :decode, :clear, :decode, :outaddr, :outaddr_sel0, :outaddr_sel1, :outdata, :outdata_sel0, :outdata_sel1
4urom :memory, :store, :outdata
5urom :pc, :load, :increment, :outaddr
6urom :rf, :store, :reset, :outdata
7urom :tmp0, :load, :load_sel0, :outaddr, :outdata
8urom :tmp1, :load, :load_sel0, :outaddr, :outdata
9urom :uart, :tx, :rx, :outdata, :outdata_sel0
10
11urom_alias :alu, :and, :op
12urom_alias :alu, :or, :op, :op_sel0
13urom_alias :alu, :xor, :op, :op_sel1
14urom_alias :alu, :add, :op, :op_sel0, :op_sel1
15urom_alias :alu, :sub, :op, :op_sel2
16urom_alias :alu, :cmp, :op, :op_sel0, :op_sel2
17urom_alias :alu, :lshift, :op, :op_sel1, :op_sel2
18urom_alias :alu, :rshift, :op, :op_sel0, :op_sel1, :op_sel2
19urom_alias :control, :set_uip, :set_uip_cond, :nocond
20urom_alias :control, :set_uip_if_nonzero, :set_uip_cond
21urom_alias :decode, :outaddr_a, :outaddr
22urom_alias :decode, :outaddr_b, :outaddr, :outaddr_sel0
23urom_alias :decode, :outaddr_uip, :outaddr, :outaddr_sel1
24urom_alias :decode, :outdata_a, :outdata
25urom_alias :decode, :outdata_b, :outdata, :outdata_sel0
26urom_alias :decode, :outdata_needmore, :outdata, :outdata_sel1
27urom_alias :tmp0, :loaddata, :load
28urom_alias :tmp0, :loadaddr, :load, :load_sel0
29urom_alias :tmp1, :loaddata, :load
30urom_alias :tmp1, :loadaddr, :load, :load_sel0
31urom_alias :uart, :outdata_txfull, :outdata
32urom_alias :uart, :outdata_rxempty, :outdata, :outdata_sel0
diff --git a/sim/.gitignore b/sim/.gitignore
new file mode 100644
index 0000000..dc3fae8
--- /dev/null
+++ b/sim/.gitignore
@@ -0,0 +1,2 @@
1/build
2/verilator
diff --git a/sim/Makefile b/sim/Makefile
new file mode 100644
index 0000000..af9d22a
--- /dev/null
+++ b/sim/Makefile
@@ -0,0 +1,12 @@
1run: build/Vtop
2 $<
3.PHONY: run
4
5build/Vtop: $(wildcard *.cpp *.sv)
6 @rm -rf verilator
7 @mkdir -p build verilator
8 verilator +1800-2017ext+sv -Wall -Wno-BLKSEQ -Wno-UNUSED -O3 -Ihdl --Mdir verilator --trace --cc --build -j --exe --top-module top $(wildcard *.cpp *.sv)
9 @ln -t build -f verilator/Vtop
10 @rm -rf verilator
11
12.SECONDARY:
diff --git a/sim/alu.sv b/sim/alu.sv
new file mode 100644
index 0000000..407b083
--- /dev/null
+++ b/sim/alu.sv
@@ -0,0 +1,76 @@
1module alu
2 #( parameter UROM = "<no file specified>"
3 , parameter UIP_BITS = 15
4 , parameter UROM_BITS = 8
5 , parameter BUS_BITS = 16
6 )
7 ( input bit clk
8 , input bit reset
9 , input bit [UIP_BITS-1:0] uip
10 , inout bit [BUS_BITS-1:0] abus
11 , inout bit [BUS_BITS-1:0] dbus
12 );
13
14bit [BUS_BITS-1:0] x;
15
16typedef enum
17 { OP
18 , OP_SEL0
19 , OP_SEL1
20 , OP_SEL2
21 , OUTADDR
22 , OUTDATA
23 } CtrlBit;
24
25bit [UROM_BITS-1:0] ctrl;
26urom#(UROM, UIP_BITS, UROM_BITS) urom(uip, ctrl);
27
28bit [2:0] sel;
29assign sel = {ctrl[OP_SEL2], ctrl[OP_SEL1], ctrl[OP_SEL0]};
30
31bit [BUS_BITS-1:0] and_result;
32bit [BUS_BITS-1:0] or_result;
33bit [BUS_BITS-1:0] xor_result;
34bit [BUS_BITS-1:0] add_result;
35bit [BUS_BITS-1:0] sub_result;
36bit [BUS_BITS-1:0] cmp_result;
37bit [BUS_BITS-1:0] lshift_result;
38bit [BUS_BITS-1:0] rshift_result;
39
40assign and_result = abus & dbus;
41assign or_result = abus | dbus;
42assign xor_result = abus ^ dbus;
43assign add_result = abus + dbus;
44assign sub_result = abus - dbus;
45assign cmp_result = {{(BUS_BITS-6){1'b0}},
46 (abus != 0) & (dbus != 0),
47 (abus != 0) | (dbus != 0),
48 (abus != 0) ^ (dbus != 0),
49 abus > dbus,
50 abus == dbus,
51 abus < dbus};
52assign lshift_result = (dbus >= BUS_BITS) ? 0 : (abus << dbus);
53assign rshift_result = (dbus >= BUS_BITS) ? 0 : (abus >> dbus);
54
55bit [BUS_BITS-1:0] newx;
56assign newx =
57 (sel == 0) ? and_result :
58 (sel == 1) ? or_result :
59 (sel == 2) ? xor_result :
60 (sel == 3) ? add_result :
61 (sel == 4) ? sub_result :
62 (sel == 5) ? cmp_result :
63 (sel == 6) ? lshift_result :
64 (sel == 7) ? rshift_result :
65 {(BUS_BITS){1'bX}};
66
67assign abus = ctrl[OUTADDR] ? x : {(BUS_BITS){1'bZ}};
68assign dbus = ctrl[OUTDATA] ? x : {(BUS_BITS){1'bZ}};
69
70always @(posedge clk) begin
71 if (ctrl[OP]) begin
72 x <= newx;
73 end
74end
75
76endmodule
diff --git a/sim/control.sv b/sim/control.sv
new file mode 100644
index 0000000..7808f61
--- /dev/null
+++ b/sim/control.sv
@@ -0,0 +1,54 @@
1module control
2 #( parameter UROM = "<no file specified>"
3 , parameter UIP_BITS = 15
4 , parameter UROM_BITS = 8
5 , parameter BUS_BITS = 16
6 , parameter CONST_0 = "<no file specified>"
7 , parameter CONST_1 = "<no file specified>"
8 , parameter RESET = ~0
9 )
10 ( input bit clk
11 , input bit reset
12 , output bit [UIP_BITS-1:0] uip
13 , inout bit [BUS_BITS-1:0] abus
14 , inout bit [BUS_BITS-1:0] dbus
15 );
16
17typedef enum
18 { HALT
19 , SET_UIP_COND
20 , NOCOND
21 , OUTADDR
22 , OUTDATA
23 } CtrlBit;
24
25bit [UROM_BITS-1:0] ctrl;
26urom#(UROM, UIP_BITS, UROM_BITS) urom(uip, ctrl);
27
28bit [UROM_BITS*2-1:0] constant;
29urom#(CONST_0, UIP_BITS, UROM_BITS) const_0(uip, constant[1*UROM_BITS-1:0*UROM_BITS]);
30urom#(CONST_1, UIP_BITS, UROM_BITS) const_1(uip, constant[2*UROM_BITS-1:1*UROM_BITS]);
31
32assign abus = ctrl[OUTADDR] ? constant : {(BUS_BITS){1'bZ}};
33assign dbus = ctrl[OUTDATA] ? constant : {(BUS_BITS){1'bZ}};
34
35bit cond;
36assign cond = (dbus != 0) || ctrl[NOCOND];
37
38always @(posedge clk) begin
39 if (reset) begin
40 uip <= RESET;
41 end else begin
42 if (! ctrl[HALT]) begin
43 if (ctrl[SET_UIP_COND] && cond) begin
44 uip <= abus[UIP_BITS-1:0];
45 end else begin
46 uip <= uip + 1;
47 end
48 end else begin
49 $finish;
50 end
51 end
52end
53
54endmodule
diff --git a/sim/decode.sv b/sim/decode.sv
new file mode 100644
index 0000000..5c9a9c9
--- /dev/null
+++ b/sim/decode.sv
@@ -0,0 +1,82 @@
1module decode
2 #( parameter UROM = "<no file specified>"
3 , parameter UIP_BITS = 15
4 , parameter UROM_BITS = 8
5 , parameter BUS_BITS = 16
6 , parameter OPCODE_BITS = 8
7 )
8 ( input bit clk
9 , input bit reset
10 , input bit [UIP_BITS-1:0] uip
11 , inout bit [BUS_BITS-1:0] abus
12 , inout bit [BUS_BITS-1:0] dbus
13 );
14
15bit [OPCODE_BITS-1:0] opcode;
16bit [BUS_BITS-1:0] a;
17bit [BUS_BITS-1:0] b;
18bit needmore;
19
20bit [UIP_BITS-1:0] new_uip;
21assign new_uip = {opcode, {(UIP_BITS-OPCODE_BITS){1'b0}}};
22
23typedef enum
24 { CLEAR
25 , DECODE
26 , OUTADDR
27 , OUTADDR_SEL0
28 , OUTADDR_SEL1
29 , OUTDATA
30 , OUTDATA_SEL0
31 , OUTDATA_SEL1
32 } CtrlBit;
33
34bit [UROM_BITS-1:0] ctrl;
35urom#(UROM, UIP_BITS, UROM_BITS) urom(uip, ctrl);
36
37bit [1:0] asel;
38assign asel = {ctrl[OUTADDR_SEL1], ctrl[OUTADDR_SEL0]};
39
40bit [1:0] dsel;
41assign dsel = {ctrl[OUTDATA_SEL1], ctrl[OUTDATA_SEL0]};
42
43bit [BUS_BITS-1:0] aout;
44assign aout =
45 (asel == 0) ? a :
46 (asel == 1) ? b :
47 (asel == 2) ? {{(BUS_BITS-UIP_BITS){1'b0}}, new_uip} :
48 {(BUS_BITS){1'bX}};
49
50assign abus = ctrl[OUTADDR] ? aout : {(BUS_BITS){1'bZ}};
51
52bit [BUS_BITS-1:0] dout;
53assign dout =
54 (dsel == 0) ? a :
55 (dsel == 1) ? b :
56 (dsel == 2) ? {{(BUS_BITS-1){1'b0}}, needmore} :
57 {(BUS_BITS){1'bX}};
58
59assign dbus = ctrl[OUTDATA] ? dout : {(BUS_BITS){1'bZ}};
60
61always @(posedge clk) begin
62 if (reset || ctrl[CLEAR]) begin
63 opcode <= 0;
64 a <= 0;
65 b <= 0;
66 needmore <= 1;
67 end else if (ctrl[DECODE]) begin
68 automatic bit m = dbus[7];
69 automatic bit i = dbus[6];
70 automatic bit [1:0] field = dbus[5:4];
71 automatic bit [3:0] shift = dbus[3:0];
72 needmore <= m;
73 if (field == 0) begin
74 opcode <= {i ? ~opcode[OPCODE_BITS-1-4:0] : opcode[OPCODE_BITS-1-4:0], shift};
75 end else if (field == 2) begin
76 a <= {i ? ~a[BUS_BITS-1-4:0] : a[BUS_BITS-1-4:0], shift};
77 end else if (field == 3) begin
78 b <= {i ? ~b[BUS_BITS-1-4:0] : b[BUS_BITS-1-4:0], shift};
79 end
80 end
81end
82endmodule
diff --git a/sim/main.cpp b/sim/main.cpp
new file mode 100644
index 0000000..ac4befa
--- /dev/null
+++ b/sim/main.cpp
@@ -0,0 +1,61 @@
1#include <cstdint>
2#include <iostream>
3#include <verilated.h>
4#include <verilated_vcd_c.h>
5
6#include "Vtop.h"
7
8std::uint64_t phases = 0;
9
10double sc_time_stamp()
11{
12 return (double)phases / 2;
13}
14
15int main(int argc, const char *argv[])
16{
17 Verilated::commandArgs(argc, argv);
18
19 Verilated::traceEverOn(true);
20 VerilatedVcdC vcd;
21
22 Vtop top;
23 top.trace(&vcd, 100 /* levels of hierarchy */);
24
25 vcd.set_time_unit("ns");
26 vcd.set_time_resolution("ns");
27 vcd.open("build/out.vcd");
28
29 std::cout << "*** RESET SEQUENCE ***\n";
30
31 top.clk = 0;
32 top.reset = 1;
33 top.eval();
34 vcd.dump(++phases);
35
36 top.clk = 1;
37 top.eval();
38 vcd.dump(++phases);
39
40 top.clk = 0;
41 top.reset = 0;
42 top.eval();
43 vcd.dump(++phases);
44
45 std::cout << "*** MAIN LOOP ***\n";
46
47 for (unsigned int i = 0; i < 10000 && !Verilated::gotFinish(); ++i) {
48 top.clk = 1;
49 top.eval();
50 vcd.dump(++phases);
51 top.clk = 0;
52 top.eval();
53 vcd.dump(++phases);
54 }
55
56 std::cout << "\n";
57
58 vcd.close();
59
60 return 0;
61}
diff --git a/sim/memory.sv b/sim/memory.sv
new file mode 100644
index 0000000..0eb1233
--- /dev/null
+++ b/sim/memory.sv
@@ -0,0 +1,35 @@
1module memory
2 #( parameter UROM = "<no file specified>"
3 , parameter UIP_BITS = 15
4 , parameter UROM_BITS = 8
5 , parameter BUS_BITS = 16
6 , parameter IMAGE = "<no file specified>"
7 , parameter BYTE_BITS = 8
8 )
9 ( input bit clk
10 , input bit reset
11 , input bit [UIP_BITS-1:0] uip
12 , inout bit [BUS_BITS-1:0] abus
13 , inout bit [BUS_BITS-1:0] dbus
14 );
15
16bit [BYTE_BITS-1:0] storage [0:(1<<BUS_BITS)-1];
17initial $readmemh(IMAGE, storage);
18
19typedef enum
20 { STORE
21 , OUTDATA
22 } CtrlBit;
23
24bit [UROM_BITS-1:0] ctrl;
25urom#(UROM, UIP_BITS, UROM_BITS) urom(uip, ctrl);
26
27assign dbus = ctrl[OUTDATA] ? {{(BUS_BITS-BYTE_BITS){1'b0}}, storage[abus]} : {(BUS_BITS){1'bZ}};
28
29always @(posedge clk) begin
30 if (ctrl[STORE]) begin
31 storage[abus] <= dbus[BYTE_BITS-1:0];
32 end
33end
34
35endmodule
diff --git a/sim/pc.sv b/sim/pc.sv
new file mode 100644
index 0000000..1a3aaee
--- /dev/null
+++ b/sim/pc.sv
@@ -0,0 +1,36 @@
1module pc
2 #( parameter UROM = "<no file specified>"
3 , parameter UIP_BITS = 15
4 , parameter UROM_BITS = 8
5 , parameter BUS_BITS = 16
6 , parameter RESET = 0
7 )
8 ( input bit clk
9 , input bit reset
10 , input bit [UIP_BITS-1:0] uip
11 , inout bit [BUS_BITS-1:0] abus
12 , inout bit [BUS_BITS-1:0] dbus
13 );
14
15bit [BUS_BITS-1:0] addr;
16
17typedef enum
18 { LOAD
19 , INCREMENT
20 , OUTADDR
21 } CtrlBit;
22
23bit [UROM_BITS-1:0] ctrl;
24urom#(UROM, UIP_BITS, UROM_BITS) urom(uip, ctrl);
25
26assign abus = ctrl[OUTADDR] ? addr : {(BUS_BITS){1'bZ}};
27
28always @(posedge clk) begin
29 if (reset) begin
30 addr <= RESET;
31 end else begin
32 addr <= (ctrl[LOAD] ? abus : addr) + (ctrl[INCREMENT] ? 1 : 0);
33 end
34end
35
36endmodule
diff --git a/sim/rf.sv b/sim/rf.sv
new file mode 100644
index 0000000..37502ce
--- /dev/null
+++ b/sim/rf.sv
@@ -0,0 +1,39 @@
1module rf
2 #( parameter UROM = "<no file specified>"
3 , parameter UIP_BITS = 15
4 , parameter UROM_BITS = 8
5 , parameter BUS_BITS = 16
6 , parameter NAME_BITS = 3
7 )
8 ( input bit clk
9 , input bit reset
10 , input bit [UIP_BITS-1:0] uip
11 , inout bit [BUS_BITS-1:0] abus
12 , inout bit [BUS_BITS-1:0] dbus
13 );
14
15bit [BUS_BITS-1:0] storage [0:(1<<NAME_BITS)-1];
16
17typedef enum
18 { STORE
19 , RESET
20 , OUTDATA
21 } CtrlBit;
22
23bit [UROM_BITS-1:0] ctrl;
24urom#(UROM, UIP_BITS, UROM_BITS) urom(uip, ctrl);
25
26assign dbus = ctrl[OUTDATA] ? storage[abus[NAME_BITS-1:0]] : {(BUS_BITS){1'bZ}};
27
28always @(posedge clk) begin
29 if (reset || ctrl[RESET]) begin
30 for (int i = 0; i < (1 << NAME_BITS); ++i)
31 storage[i] <= 0;
32 end else begin
33 if (ctrl[STORE]) begin
34 storage[abus[NAME_BITS-1:0]] <= dbus;
35 end
36 end
37end
38
39endmodule
diff --git a/sim/tmp.sv b/sim/tmp.sv
new file mode 100644
index 0000000..61e35f7
--- /dev/null
+++ b/sim/tmp.sv
@@ -0,0 +1,41 @@
1module tmp
2 #( parameter UROM = "<no file specified>"
3 , parameter UIP_BITS = 15
4 , parameter UROM_BITS = 8
5 , parameter BUS_BITS = 16
6 )
7 ( input bit clk
8 , input bit reset
9 , input bit [UIP_BITS-1:0] uip
10 , inout bit [BUS_BITS-1:0] abus
11 , inout bit [BUS_BITS-1:0] dbus
12 );
13
14bit [BUS_BITS-1:0] x;
15
16typedef enum
17 { LOAD
18 , LOAD_SEL0
19 , OUTADDR
20 , OUTDATA
21 } CtrlBit;
22
23bit [UROM_BITS-1:0] ctrl;
24urom#(UROM, UIP_BITS, UROM_BITS) urom(uip, ctrl);
25
26bit [0:0] sel;
27assign sel = {ctrl[LOAD_SEL0]};
28
29assign abus = ctrl[OUTADDR] ? x : {(BUS_BITS){1'bZ}};
30assign dbus = ctrl[OUTDATA] ? x : {(BUS_BITS){1'bZ}};
31
32always @(posedge clk) begin
33 if (ctrl[LOAD]) begin
34 x <=
35 (sel == 0) ? dbus :
36 (sel == 1) ? abus :
37 {(BUS_BITS){1'bX}};
38 end
39end
40
41endmodule
diff --git a/sim/top.sv b/sim/top.sv
new file mode 100644
index 0000000..6773739
--- /dev/null
+++ b/sim/top.sv
@@ -0,0 +1,27 @@
1module top
2 #( parameter UIP_BITS = 15
3 , parameter UROM_BITS = 8
4 , parameter BUS_BITS = 16
5 , parameter MEM_BITS = 8
6 )
7 ( input bit clk // verilator public
8 , input bit reset // verilator public
9 );
10
11bit [UIP_BITS-1:0] uip;
12bit [BUS_BITS-1:0] abus;
13bit [BUS_BITS-1:0] dbus;
14
15alu #("../out/alu.bin", UIP_BITS, UROM_BITS, BUS_BITS) alu(clk, reset, uip, abus, dbus);
16control #("../out/control.bin", UIP_BITS, UROM_BITS, BUS_BITS, "../out/consts.0.bin", "../out/consts.1.bin", 'h7ff8) control(clk, reset, uip, abus, dbus);
17decode #("../out/decode.bin", UIP_BITS, UROM_BITS, BUS_BITS, 12) decode(clk, reset, uip, abus, dbus);
18memory #("../out/memory.bin", UIP_BITS, UROM_BITS, BUS_BITS, "../out/image.hex", MEM_BITS) memory(clk, reset, uip, abus, dbus);
19pc #("../out/pc.bin", UIP_BITS, UROM_BITS, BUS_BITS, 0) pc(clk, reset, uip, abus, dbus);
20rf #("../out/rf.bin", UIP_BITS, UROM_BITS, BUS_BITS, 3) rf(clk, reset, uip, abus, dbus);
21tmp #("../out/tmp0.bin", UIP_BITS, UROM_BITS, BUS_BITS) tmp0(clk, reset, uip, abus, dbus);
22tmp #("../out/tmp1.bin", UIP_BITS, UROM_BITS, BUS_BITS) tmp1(clk, reset, uip, abus, dbus);
23uart #("../out/uart.bin", UIP_BITS, UROM_BITS, BUS_BITS) uart(clk, reset, uip, abus, dbus);
24
25//always @(negedge clk) $display("pc=%x uip=%x abus=%x dbus=%x tmp0=%x tmp1=%x alu=%x regs=%x:%x:%x:...:%x", pc.addr, uip, abus, dbus, tmp0.x, tmp1.x, alu.x, rf.storage[0], rf.storage[1], rf.storage[2], rf.storage[7]);
26
27endmodule
diff --git a/sim/uart.sv b/sim/uart.sv
new file mode 100644
index 0000000..3b434da
--- /dev/null
+++ b/sim/uart.sv
@@ -0,0 +1,47 @@
1module uart
2 #( parameter UROM = "<no file specified>"
3 , parameter UIP_BITS = 15
4 , parameter UROM_BITS = 8
5 , parameter BUS_BITS = 16
6 )
7 ( input bit clk
8 , input bit reset
9 , input bit [UIP_BITS-1:0] uip
10 , inout bit [BUS_BITS-1:0] abus
11 , inout bit [BUS_BITS-1:0] dbus
12 );
13
14bit txfull;
15bit rxempty;
16
17assign txfull = 0;
18assign rxempty = 0;
19
20typedef enum
21 { TX
22 , RX
23 , OUTDATA
24 , OUTDATA_SEL0
25 } CtrlBit;
26
27bit [UROM_BITS-1:0] ctrl;
28urom#(UROM, UIP_BITS, UROM_BITS) urom(uip, ctrl);
29
30bit [0:0] sel;
31assign sel = {ctrl[OUTDATA_SEL0]};
32
33bit [BUS_BITS-1:0] dout;
34assign dout =
35 (ctrl[RX]) ? {(BUS_BITS){1'b1}} :
36 (sel == 0) ? {{(BUS_BITS-1){1'b0}}, txfull} :
37 (sel == 1) ? {{(BUS_BITS-1){1'b0}}, rxempty} :
38 {(BUS_BITS){1'bX}};
39
40assign dbus = ctrl[OUTDATA] ? dout : {(BUS_BITS){1'bZ}};
41
42always @(posedge clk) begin
43 if (ctrl[TX])
44 $display("tx %x", dbus[7:0]);
45end
46
47endmodule
diff --git a/sim/urom.sv b/sim/urom.sv
new file mode 100644
index 0000000..e88f6d7
--- /dev/null
+++ b/sim/urom.sv
@@ -0,0 +1,19 @@
1module urom
2 #( parameter UROM = "<no file specified>"
3 , parameter ADDR_BITS = 15
4 , parameter DATA_BITS = 8
5 )
6 ( input bit [ADDR_BITS-1:0] addr
7 , output bit [DATA_BITS-1:0] data
8 );
9
10bit [DATA_BITS-1:0] storage [0:(1<<ADDR_BITS)-1];
11initial begin
12 automatic int fh;
13 fh = $fopen(UROM, "rb");
14 $fread(storage, fh);
15end
16
17assign data = storage[addr];
18
19endmodule
diff --git a/uasm.rb b/uasm.rb
new file mode 100755
index 0000000..c8a8967
--- /dev/null
+++ b/uasm.rb
@@ -0,0 +1,174 @@
1#!/usr/bin/ruby -w
2
3OPCODE_BITS = 12
4UROM_BITS = 15
5UIP_BITS_PER_OPCODE = UROM_BITS - OPCODE_BITS
6
7$stdout.write(<<END)
8 OPCODE_BITS = #{OPCODE_BITS}
9 UROM_BITS = #{UROM_BITS}
10UIP_BITS_PER_OPCODE = #{UIP_BITS_PER_OPCODE} (max #{(1<<UIP_BITS_PER_OPCODE)-1} uops (+1 eom) per inst)
11
12END
13
14$uroms = {consts: [0] * (1 << UROM_BITS)}
15$urom_sizes = {consts: 16}
16$insts = {}
17
18$this_inst = nil
19$this_uop = nil
20
21$next_opcode = 0
22$next_vector = (1 << OPCODE_BITS) - 1
23
24system("rm -rf out; mkdir -p out")
25
26def urom(name, *bits)
27 throw "non-unique bit names" unless bits == bits.uniq
28 throw "µrom with this name already defined" if $uroms.member?(name)
29 $uroms[name] = [0] * (1 << UROM_BITS)
30 $urom_sizes[name] = bits.size
31 proxy = Object.new
32 $stdout.write("\n\t#{name}:\n")
33 bitmap = {}
34 bits.each_with_index do | bit, idx |
35 if bits.size > 8
36 $stdout.write("\t\t#{idx >> 3}.#{idx & 0x7}\t#{bit}\n")
37 else
38 $stdout.write("\t\t#{idx}\t#{bit}\n")
39 end
40 bitmap[bit] = 1 << idx
41 proxy.define_singleton_method(bit) do
42 if $this_uop
43 $this_uop[name] |= 1 << idx
44 else
45 uop do
46 $this_uop[name] |= 1 << idx
47 end
48 end
49 end
50 end
51 proxy.instance_variable_set(:@bitmap, bitmap)
52 instance_variable_set("@#{name}", proxy)
53end
54
55def urom_alias(urom, name, *bits)
56 merged = 0
57 proxy = instance_variable_get("@#{urom}")
58 bitmap = proxy.instance_variable_get(:@bitmap)
59 throw "Name already in use" if bitmap.member?(name)
60 bits.each do | bit |
61 merged |= bitmap[bit]
62 end
63 bitmap[name] = merged
64 proxy.define_singleton_method(name) do
65 if $this_uop
66 $this_uop[urom] |= merged
67 else
68 uop { $this_uop[urom] |= merged }
69 end
70 end
71 proxy.instance_variable_set(:@bitmap, bitmap)
72end
73
74def inst(pattern, vector=false, &code)
75 throw "nested instruction" if $this_inst
76 throw "instruction with this pattern already defined" if $insts.member?(pattern)
77 throw "too many opcodes" if $next_opcode > $next_vector
78 $this_opnum = vector ? $next_vector : $next_opcode
79 $stdout.write("\t#{$this_opnum.to_s(16)}\t#{($this_opnum << UIP_BITS_PER_OPCODE).to_s(16)}\t#{pattern}\n")
80 $this_inst = []
81 code.call
82 if not vector
83 $eom ||= uip()
84 uop { @decode.clear; @control.set_uip; constaddr($insts["!bom"] << UIP_BITS_PER_OPCODE) }
85 end
86 $this_inst.each_with_index do | uop, idx |
87 uip = ($this_opnum << UIP_BITS_PER_OPCODE) + idx
88 uop.each do | urom, entry |
89 $uroms[urom][uip] = entry
90 end
91 end
92 $insts[pattern] = $this_opnum
93 $this_opnum = nil
94 $this_inst = nil
95 if vector
96 $next_vector -= 1
97 else
98 $next_opcode += 1
99 end
100end
101
102def vector(name, &code)
103 inst("!#{name}", true, &code)
104end
105
106def uop(&code)
107 throw "not in instruction" unless $this_inst
108 throw "nested uop" if $this_uop
109 throw "too many uops" if $this_inst.size >= (1 << UIP_BITS_PER_OPCODE)
110 $this_uop = {}
111 $uroms.each_key do | urom |
112 $this_uop[urom] = 0
113 end
114 code.call
115 $this_inst << $this_uop
116 $this_uop = nil
117end
118
119def const(value)
120 throw "Value out of range" if value < 0 or value > 0xffff
121 if $this_uop
122 $this_uop[:consts] = value
123 else
124 uop do
125 $this_uop[:consts] = value
126 end
127 end
128end
129
130def constaddr(value)
131 const(value)
132 @control.outaddr
133end
134
135def constdata(value)
136 const(value)
137 @control.outdata
138end
139
140def uip()
141 throw "not in instruction" unless $this_inst
142 return ($this_opnum << UIP_BITS_PER_OPCODE) + $this_inst.size
143end
144
145$stdout.write("Control wires:\n")
146load "modules.rb"
147
148$stdout.write("\nOpcodes:\n")
149load "vectors.rb"
150load "insts.rb"
151
152$stdout.write("\nWriting µrom contents:\n")
153$uroms.each do | urom, data |
154 $stdout.write("\t#{urom}...")
155 $stdout.flush
156 if $urom_sizes[urom] > 8
157 0.upto(($urom_sizes[urom] / 8.0).ceil - 1) do | bank |
158 $stdout.write(" #{bank}")
159 $stdout.flush
160 File.open("out/#{urom}.#{bank}.bin", "wb") do | fh |
161 data.each do | word |
162 fh.write(((word >> (8 * bank)) & 0xff).chr)
163 end
164 end
165 end
166 else
167 File.open("out/#{urom}.bin", "wb") do | fh |
168 data.each do | byte |
169 fh.write(byte.chr)
170 end
171 end
172 end
173 $stdout.write("\n")
174end
diff --git a/vectors.rb b/vectors.rb
new file mode 100644
index 0000000..62b58d5
--- /dev/null
+++ b/vectors.rb
@@ -0,0 +1,7 @@
1vector :bom do
2 $start_of_bom = uip()
3 decode_loop = uip()
4 uop { @pc.increment; @pc.outaddr; @memory.outdata; @decode.decode }
5 uop { @decode.outdata_needmore; @control.set_uip_if_nonzero; constaddr(decode_loop) }
6 uop { @decode.outaddr_uip; @control.set_uip }
7end