db47h / hwsim Goto Github PK
View Code? Open in Web Editor NEWA Go package that provides the necessary tools to build a virtual CPU using Go as a hardware description language and run it.
License: MIT License
A Go package that provides the necessary tools to build a virtual CPU using Go as a hardware description language and run it.
License: MIT License
The loop detection implemented in eeb49ed only happens at runtime and identifying components involved in the loop is impossible. This check should be done statically.
implement proper benchmarks.
This would allow using bus notation for buses with both in and out pins
For example, a lookahead carry unit has 5 carry pins, one input, four output:
Chip("LCU", "p[4], g[4], c[0..0]", "p, g, c[1..4]", hw.Parts{
// ...
})
When building a PC like this:
bit := Chip("bit", "in, load", "out",
hl.Mux("a=out, b=in, sel=load, out=mux"),
hl.DFF("in=mux, out=out"),
)
register16, err := Chip("register", "in[16], load", "out[16]",
bit("in=in[0], load=load, out=out[0]"),
bit("in=in[1], load=load, out=out[1]"),
// ...
bit("in=in[15], load=load, out=out[15]"))
mux16 := hl.MuxN(16)
pc, err := Chip("counter", "in[16], inc, load, reset", "out[16]",
register16("in[0..15]=rin[0..15], out[0..15]=out[0..15], load=rload"),
hl.OrNWay(3)("in[0]=inc, in[1]=load, in[2]=reset, out=rload"),
hack.Inc16("in[0..15]=out[0..15], out[0..15]=iout[0..15]"),
// increment out?
mux16("a[0..15]=out[0..15], b[0..15]=iout[0..15], sel=inc, out[0..15]=inc[0..15]"),
// load ?
mux16("a[0..15]=inc[0..15], b[0..15]=in[0..15], sel=load, out[0..15]=ld[0..15]"),
// reset ?
mux16("a[0..15]=ld[0..15], sel=reset, out[0..15]=rin[0..15]"),
)
There's a wire loop. More details to come.
Lines 237 to 247 in ae8bccb
If len(ups)
is for example 9 and workers
is 8, it will start only 9 / ((9/8)+1) = 4 workers.
With Chip
now taking strings as arguments and the addition of MakePart
, shortened names like IO
, IOs
can now be turned back into something more meaningful.
The current implementation is flawed:
A circuit allocates a bunch of components across several worker goroutines. At each step:
This sort of works, but it's pretty bad performance wise. The problem is with the simulation implementation:
The simulator is built as an array of individual wires (think [stripboard]). It works like a double-buffer with a "current state" array and a "next state" array. At every tick of the simulation:
- all components are updated:
- input states are read from the "current state" array
- output states are written to the "next state" array
- the "current state" and "next state" arrays are swapped.
So this cannot be fixed by removing Step
and allow the workers to run for a full clock cycle since the wire buffer needs to be swapped after each update of all components.
Solutions:
That's easily done and will allow changing a few strings to int internally.
This is a matter of perspective: It makes much more sense from a Go perspective (in which case Socket must go in favor of some more aptly named interface)
type NewFn func (w Wires) // or Wiring or ?
But then we have Circuit
and other Chip
...
almost none to be seen !
Change pins to a full fledged Wire:
type Wire struct {
value bool
clk bool // clock cycle for value
src Updater
fanout []Updater
}
func (w *Wire) Set(clk bool, value) {
if w.clk != clk {
w.clk, w.value = clk, value
}
}
func (w *Wire) Get(clk bool) bool {
if w.clk != clk {
w.src.Update(clk)
}
return w.value
}
With wires driving the simulation. Need to find a way to identify a "hot wire" that will trigger the whole simulation.
We could also have a wire trigger a cascading update on Set
(by updating all in fanout), but then components would have to keep track of time as well.
This would make it easier to test both builtin components and more complex chips in one go.
Started in daced20
This will make major api changes easier as it will allow ignoring hwlib until the changes are complete and fully tested.
The idea is to make it doable, NOT to move Chip()
.
This will require exporting a few methods in Socket, mostly.
For custom components, what if we did something like this:
type Mux8 struct {
In [8]int `hw:in`
Sel int `hw:in`
Out [8]int `hw:out`
}
func (m *Mux8) Update(c *Circuit) {
// ...
}
// Along with a Component interface
type Component interface {
Update(c *Circuit)
}
And use reflect
to get the specs of a part. Chip.mount
could then instantiate parts as needed and init their input/outputs.
Consider Update(clk int)
instead of Update(clk bool)
; this would eliminate the need to reset all pin's clk
in Circuit.update
See #21 (comment)
It doesn't belong here.
The new simulation algorithm breaks with loops.
See #16
Followup on #16
Need to find a way to access the const *Wires
Omitted output pins are nil.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.