summaryrefslogtreecommitdiff
path: root/hdl
diff options
context:
space:
mode:
Diffstat (limited to 'hdl')
-rw-r--r--hdl/core.py184
1 files changed, 143 insertions, 41 deletions
diff --git a/hdl/core.py b/hdl/core.py
index 655af68..c1e38cc 100644
--- a/hdl/core.py
+++ b/hdl/core.py
@@ -1,4 +1,6 @@
+from curses.ascii import SI
from multiprocessing import dummy
+from tkinter import S
from amaranth import *
from amaranth.sim import Simulator, Settle, Delay
from enum import Enum, unique
@@ -6,49 +8,145 @@ from enum import Enum, unique
from utils import cmd
-# class Reg(Elaboratable):
-# def __init__(self):
-# self.rd_addr = Signal(4)
-# self.rs1_addr = Signal(4)
-# self.rs2_addr = Signal(4)
-
-# self.rd = Signal(32)
-# self.rs1 = Signal(32)
-# self.rs2 = Signal(32)
-
-# self.zx = Signal(32)
-# self.ax = Signal(32)
-# self.bx = Signal(32)
-# self.bx = Signal(32)
-# self.cx = Signal(32)
-# self.dx = Signal(32)
-# self.ex = Signal(32)
-# self.fx = Signal(32)
-# self.gx = Signal(32)
-# self.hx = Signal(32)
-# self.hi = Signal(32)
-# self.lo = Signal(32)
-# self.fg = Signal(32)
-# self.cr = Signal(32)
-# self.ip = Signal(32)
-# self.sp = Signal(32)
-# self.ja = Signal(32)
-
-# self.reg_ar = Array([self.zx, self.ax, self.bx, self.cx, self.dx, self.ex, self.fx, self.gx, self.hx, self.hi, self.lo, self.fg, self.cr, self.ip, self.sp, self.ja])
-
-# # TODO: add support for storing multiplication result
-# self.ports = [self.rd_addr, self.rs1_addr, self.rs2_addr, self.rd, self.rs1, self.rs2, self.ip]
+class Reg(Elaboratable):
+ def __init__(self):
+ # enable write
+ self.wr_en = Signal(1)
-# def elaborate(self, platform=None):
-# m = Module()
+ # input and output addresses
+ self.rd_addr = Signal(4)
+ self.rs1_addr = Signal(4)
+ self.rs2_addr = Signal(4)
-# with m.If(self.rd_addr != 0):
-# m.d.sync += self.reg_ar[self.rd_addr].eq(self.rd)
+ # input and output signals
+ self.rd = Signal(32)
+ self.rs1 = Signal(32)
+ self.rs2 = Signal(32)
-# m.d.comb += self.rs1.eq(self.reg_ar[self.rs1_addr])
-# m.d.comb += self.rs2.eq(self.reg_ar[self.rs2_addr])
+ # alu status signals
+ self.alu_flgs = Signal(5)
-# return m
+ self.stack_instr = Signal(1)
+ self.stack_down_up = Signal(1)
+
+ ##################################################################
+
+ # activated when interupt is triggered
+ self.interupt = Signal(1)
+ # return from interrupt special
+ self.iret = Signal(1)
+ # jump signal to jump and link (swap ip and cs0)
+ self.jump = Signal(1)
+
+ #################################################################
+ # None of the 3 signals above should ever be set at the same time
+ #################################################################
+
+
+ # internal signals
+ self._user_mode = Signal(1)
+ self._interupt = Signal(1)
+ self._sp_write = Signal(1)
+
+ self.zx = Signal(32) #0
+ self.ax = Signal(32) #1
+ self.bx = Signal(32) #2
+ self.bx = Signal(32) #3
+ self.cx = Signal(32) #4
+ self.dx = Signal(32) #5
+ self.ex = Signal(32) #6
+ self.fx = Signal(32) #7
+ self.gx = Signal(32) #8
+ self.hx = Signal(32) #9
+ self.ip = Signal(32) #10
+ self.sp = Signal(32) #11
+ self.flg = Signal(32) #12
+ self.cs0 = Signal(32) #13
+ self.cs1 = Signal(32) #14
+ self.cs2 = Signal(32) #15
+ self.pda = Signal(32) #16
+
+ # for sake of modularity, make bit locations easily configurable
+ setattr(self.flg, 'c', self.flg[0])
+ setattr(self.flg, 'ov', self.flg[1])
+ setattr(self.flg, 'z', self.flg[2])
+ setattr(self.flg, 'n', self.flg[3])
+ setattr(self.flg, 'od', self.flg[4])
+ setattr(self.flg, 'int', self.flg[16])
+ setattr(self.flg, 'user_mode', self.flg[17])
+ setattr(self.flg, 'page_en', self.flg[18])
+
+
+ reg_list = [self.zx, self.ax, self.bx, self.cx, self.dx, self.ex, self.fx, self.gx, self.hx, self.ip, self.sp, self.flg, self.cs0, self.cs1, self.cs2, self.pda]
+ for idx, reg in enumerate(reg_list):
+ setattr(reg, 'idx', idx) # set idx attribute to each register
+
+ self.reg_arr = Array(reg_list)
+ self.ports = [self.wr_en, self.alu_flgs, self.jump, self.interupt, self.iret, self.stack_instr, self.stack_down_up, self.rd_addr, self.rs1_addr, self.rs2_addr, self.rd, self.rs1, self.rs2, self.ip]
+
+ def elaborate(self, platform=None):
+ m = Module()
+
+ # user mode override
+ m.d.comb += self._interupt.eq(self.flg.int & self.interupt) # if the sw guy don't want to be interupted, don't
+ m.d.comb += self._user_mode.eq(self.flg.user_mode & ~self._interupt)
+
+ # toggle ip and cs0
+ with m.If(self.jump | self._interupt | self.iret):
+ m.d.sync += self.cs0.eq(self.ip)
+ m.d.sync += self.ip.eq(self.cs0)
+ with m.Else():
+ m.d.sync += self.ip.eq(self.ip + 1) # increment ip only on normal operation
+
+ with m.If(self._interupt):
+ m.d.sync += self.cs1.eq(self.sp)
+ m.d.sync += self.cs2.eq(self.flg)
+ m.d.sync += self.flg.user_mode.eq(0) # set to system mode or iret cannot be used
+ m.d.sync += self.flg.int.eq(0) # clear int flag, essential because another interrupt can be triggered without this
+ with m.Elif(self.iret):
+ m.d.sync += self.sp.eq(self.cs1)
+ m.d.sync += self.flg.eq(self.cs2)
+
+ m.d.comb += self._sp_write.eq(0)
+
+ # writeback setup
+ with m.If(self.wr_en):
+ with m.Switch(self.rd_addr):
+ with m.Case(self.zx.idx): # do not write to zero register
+ pass
+ with m.Case(self.ip.idx): #do not directly write to ip register
+ pass
+ with m.Case(self.flg.idx):
+ # mask top half of register to prevent writing to flags in user mode
+ m.d.sync += self.flg.eq(self.rd & Cat(Const(0xFFFF, 16), Repl(~self._user_mode, 16)))
+ with m.Case(self.sp.idx):
+ m.d.comb += self._sp_write.eq(1)
+ m.d.sync += self.sp.eq(self.rd)
+ with m.Case():
+ m.d.sync += self.flg.eq(Cat(self.alu_flgs, self.flg[len(self.alu_flgs):])) # update flags if register is not being written to
+ m.d.sync += self.reg_arr[self.rd_addr].eq(self.rd)
+
+ with m.If(~self._sp_write & self.stack_instr):
+ with m.If(self.stack_down_up):
+ m.d.sync += self.sp.eq(self.sp - 1)
+ with m.Else():
+ m.d.sync += self.sp.eq(self.sp + 1)
+
+
+ ### Combination signal outputs ###
+ with m.Switch(self.rs1_addr):
+ with m.Case(self.flg.idx):
+ m.d.comb += self.rs1.eq(self.flg & Cat(Const(0xFFFF, 16), Repl(~self._user_mode, 16)))
+ with m.Case():
+ m.d.comb += self.rs1.eq(self.reg_arr[self.rs1_addr])
+
+ with m.Switch(self.rs2_addr):
+ with m.Case(self.flg.idx):
+ m.d.comb += self.rs2.eq(self.flg & Cat(Const(0xFFFF, 16), Repl(~self._user_mode, 16)))
+ with m.Case():
+ m.d.comb += self.rs2.eq(self.reg_arr[self.rs2_addr])
+
+ return m
# class ASAP32Core(Elaboratable):
@@ -323,6 +421,10 @@ def test_alu(filename="alu.vcd"):
sim.run()
+
if __name__ == '__main__':
- hdl = ALU()
- cmd(hdl, test_alu)
+ reg = Reg()
+ cmd(reg, None)
+
+ # hdl = ALU()
+ # cmd(hdl, test_alu)