summaryrefslogtreecommitdiff
path: root/uasm.rb
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 /uasm.rb
downloadbreadboarding-60e1775b874015a3451e4bde10a8eb30701b1165.tar.xz
Initial commit.
Diffstat (limited to 'uasm.rb')
-rwxr-xr-xuasm.rb174
1 files changed, 174 insertions, 0 deletions
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